/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xui_lib.component.banner;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.component.banner.anim.BaseAnimator;
import com.xuexiang.xui_lib.util.Log;

import java.util.ArrayList;
import java.util.List;

import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_CONTENT;

/**
 * 指示器布局
 *
 * @since 2021-04-28
 */
public class CircleIndicator extends DependentLayout {
    private static final String TAG = "CircleIndicator";
    private static final String CORNER = "CORNER";
    private static final String RECTANGLE = "RECTANGLE";
    private static final String DRAWABLE_RESOURCE = "DRAWABLE_RESOURCE";
    private Image.ScaleMode scaleMode = Image.ScaleMode.ZOOM_CENTER;
    private static final float scaleSize = 1.5f;
    private static final int ten = 10;
    private static final int twenty = 10;
    private int indicatorDefaultSelectRes;
    private int indicatorDefaultUnselectRes;
    private int shapeIndicatorUnselectOval;
    private int shapeIndicatorSelectOval;
    private boolean isShowText;
    private int indicatorWidth;
    private int indicatorHeight;
    private int indicatorCornerRadius;
    private String barColor;
    private String indicatorStyle;
    private String indicatorGravity;
    private int count;
    private int[] pageIndicatorId;
    private Text bannerText;
    private DirectionalLayout circleIndicator;
    private List<String> indicatorStrings;
    private List<Image> mPointViews;
    private Class<? extends BaseAnimator> mSelectAnimClass;
    //private Class<? extends BaseAnimator> mUnselectAnimClass;

    /**
     * 构造参数
     *
     * @param context
     */
    public CircleIndicator(Context context) {
        super(context);
    }

    /**
     * 构造参数
     *
     * @param context
     * @param attrSet
     */
    public CircleIndicator(Context context, AttrSet attrSet) {
        super(context, attrSet);
        initView(getContext()); // 初始化布局
    }

    private void initView(Context context) {
        indicatorStrings = new ArrayList<>();
        mPointViews = new ArrayList<>();
        LayoutScatter instance = LayoutScatter.getInstance(context);
        Component component = instance.parse(ResourceTable.Layout_circle_indicator, this, true);
        circleIndicator = (DirectionalLayout) component.findComponentById(ResourceTable.Id_circleIndicator);
        bannerText = (Text) component.findComponentById(ResourceTable.Id_bannerText);
    }

    /**
     * 指示器圆球宽度
     *
     * @param indicatorWidth
     */
    public void setIndicatorWidth(int indicatorWidth) {
        this.indicatorWidth = indicatorWidth;
    }

    /**
     * 指示器圆球高度
     *
     * @param indicatorHeight
     */
    public void setIndicatorHeight(int indicatorHeight) {
        this.indicatorHeight = indicatorHeight;
    }

    /**
     * 指示器布局位置
     *
     * @param indicatorGravity
     */
    public void setIndicatorGravity(String indicatorGravity) {
        this.indicatorGravity = indicatorGravity;
    }

    /**
     * 指示器是否显示文本
     *
     * @param isShow
     */
    public void setShowText(boolean isShow) {
        this.isShowText = isShow;
    }

    /**
     * 是否设置底部背景颜色
     *
     * @param barColor
     */

    public void setBarColor(String barColor) {
        this.barColor = barColor;
    }

    /**
     * 指示器圆球形状
     *
     * @param indicatorStyle
     */
    public void setIndicatorStyle(String indicatorStyle) {
        this.indicatorStyle = indicatorStyle;
    }

    /**
     * 指示器形状角度
     *
     * @param indicatorCornerRadius
     */
    public void setIndicatorCornerRadius(int indicatorCornerRadius) {
        this.indicatorCornerRadius = indicatorCornerRadius;
    }

    /**
     * 选中的资源图片
     *
     * @param indicatorDefaultSelectRes
     */
    public void setIndicatorDefaultSelectRes(int indicatorDefaultSelectRes) {
        this.indicatorDefaultSelectRes = indicatorDefaultSelectRes;
    }

    /**
     * 未选中的资源图片
     *
     * @param indicatorDefaultUnselectRes
     */
    public void setIndicatorDefaultUnselectRes(int indicatorDefaultUnselectRes) {
        this.indicatorDefaultUnselectRes = indicatorDefaultUnselectRes;
    }

    /**
     * 未选中的自定义圆
     *
     * @param shapeIndicatorUnselectOval
     */
    public void setShapeIndicatorUnselectOval(int shapeIndicatorUnselectOval) {
        this.shapeIndicatorUnselectOval = shapeIndicatorUnselectOval;
    }

    /**
     * 选中的自定义圆
     *
     * @param shapeIndicatorSelectOval
     */
    public void setShapeIndicatorSelectOval(int shapeIndicatorSelectOval) {
        this.shapeIndicatorSelectOval = shapeIndicatorSelectOval;
    }

    /**
     * 设置显示器选中动画
     *
     * @param selectAnimClass 选中动画
     * @return 返回当前CircleIndicator对象
     */
    public CircleIndicator setSelectAnimClass(Class<? extends BaseAnimator> selectAnimClass) {
        this.mSelectAnimClass = selectAnimClass;
        return this;
    }

    /**
     * 设置显示器未选中动画
     *
     * @param unselectAnimClass 未选中动画
     * @return 返回当前CircleIndicator对象
     */
    public CircleIndicator setUnselectAnimClass(Class<? extends BaseAnimator> unselectAnimClass) {
        //this.mUnselectAnimClass = unselectAnimClass;
        return this;
    }

    /**
     * 设置指示器文本数据
     *
     * @param stringList
     */
    public void setViewData(List<String> stringList) {
        this.indicatorStrings = stringList;
        count = stringList.size();
        createCircleIndicator();
    }

    /**
     * 设置第一个指示器放大1.5倍
     */
    public void setFirstIndicator() {
        // 默认给第一个放大1.5倍
        if (CORNER.equals(indicatorStyle) && mSelectAnimClass != null) {
            Image image = mPointViews.get(0);
            image.setScale(scaleSize, scaleSize);
        }
    }

    /**
     * 设置指示器
     *
     * @param position
     */
    public void setIndicator(int position) {
        try {
            if (DRAWABLE_RESOURCE.equals(indicatorStyle)) {
                for (int ii = 0; ii < mPointViews.size(); ii++) {
                    mPointViews.get(ii).setPixelMap(pageIndicatorId[0]);
                }
                Image image = mPointViews.get(position);
                image.setPixelMap(pageIndicatorId[1]); // 选中
            } else if (RECTANGLE.equals(indicatorStyle)) { // 矩形
                for (int ii = 0; ii < mPointViews.size(); ii++) {
                    mPointViews.get(ii).setRotation(0);
                    mPointViews.get(ii).setBackground(getShapeElement("#88ffffff"));
                }
                Image image = mPointViews.get(position);
                image.setBackground(getShapeElement("#ffffff")); // 选中
                if (mSelectAnimClass != null) {
                    BaseAnimator baseAnimator = mSelectAnimClass.newInstance();
                    baseAnimator.playOn(image);
                }
            } else {
                for (int ii = 0; ii < mPointViews.size(); ii++) {
                    mPointViews.get(ii).setScale(1.0f, 1.0f);
                    mPointViews.get(ii).setBackground(new ShapeElement(getContext(), pageIndicatorId[0]));
                }
                Image image1 = mPointViews.get(position);
                image1.setBackground(new ShapeElement(getContext(), pageIndicatorId[1])); // 选中
                if (mSelectAnimClass != null) {
                    BaseAnimator baseAnimator = mSelectAnimClass.newInstance();
                    baseAnimator.playOn(image1);
                }
            }
        } catch (IllegalAccessException e) {
            Log.e(TAG, "setIndicator IllegalAccessException" + e.getLocalizedMessage());
        } catch (InstantiationException e) {
            Log.e(TAG, "setIndicator InstantiationException" + e.getLocalizedMessage());
        }
    }

    /**
     * 根据轮播图切换文本
     *
     * @param position
     */
    public void setTextShow(int position) {
        bannerText.setText(indicatorStrings.get(position));
    }

    /**
     * 设置指示器位置
     *
     * @param gravity
     */
    private void setPageIndicatorAlign(String gravity) {
        // 设置底部指示器背景颜色
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setShape(ShapeElement.RECTANGLE);
        shapeElement.setRgbColor(RgbColor.fromArgbInt(Color.getIntColor(barColor)));
        circleIndicator.setBackground(shapeElement);
        LayoutConfig layoutConfig = (LayoutConfig) bannerText.getLayoutConfig();
        switch (gravity) {
            case "LEFT":
                circleIndicator.setAlignment(LayoutAlignment.LEFT);
                layoutConfig.addRule(LayoutConfig.ALIGN_PARENT_RIGHT);
                layoutConfig.addRule(LayoutConfig.ALIGN_PARENT_BOTTOM);
                bannerText.setLayoutConfig(layoutConfig);
                break;
            case "RIGHT":
                circleIndicator.setAlignment(LayoutAlignment.RIGHT);
                layoutConfig.addRule(LayoutConfig.ALIGN_PARENT_LEFT);
                layoutConfig.addRule(LayoutConfig.ALIGN_PARENT_BOTTOM);
                bannerText.setLayoutConfig(layoutConfig);
                break;
            case "CENTER":
                circleIndicator.setAlignment(LayoutAlignment.CENTER);
                bannerText.setVisibility(Component.HIDE);
                break;
            default:
                break;
        }
    }

    /**
     * 根据类型创建不同类型的指示器
     */
    private void createCircleIndicator() {
        setPageIndicatorAlign(indicatorGravity);
        if (DRAWABLE_RESOURCE.equals(indicatorStyle)) { // 使用图片资源
            pageIndicatorId = new int[]{indicatorDefaultUnselectRes, indicatorDefaultSelectRes};
            setResource(pageIndicatorId);
        } else if (CORNER.equals(indicatorStyle)) { // 圆形
            pageIndicatorId = new int[]{shapeIndicatorUnselectOval, shapeIndicatorSelectOval};
            setShapeOvalElement(pageIndicatorId);
        } else { // 矩形
            setShapeRectangleElement();
        }

        if (isShowText) { // 是否显示文本
            bannerText.setText(indicatorStrings.get(0)); // 先默认显示第一个
        } else {
            bannerText.setVisibility(HIDE);
        }
    }

    /**
     * 设置资源图片
     *
     * @param resource
     */
    private void setResource(int[] resource) {
        for (int ii = 0; ii < count; ii++) {
            Image pointView = new Image(getContext());
            DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(MATCH_CONTENT, MATCH_CONTENT);
            params.width = indicatorWidth;
            params.height = indicatorHeight;
            pointView.setWidth(indicatorWidth);
            pointView.setHeight(indicatorHeight);
            pointView.setScaleMode(scaleMode);
            if (ii == 0) {
                pointView.setPixelMap(resource[1]);
            } else {
                pointView.setPixelMap(resource[0]);
            }
            params.setMargins(ten, twenty, ten, twenty);
            mPointViews.add(pointView);
            circleIndicator.addComponent(pointView, params);
        }
    }

    /**
     * 设置圆形
     *
     * @param shapeOvalElement
     */
    private void setShapeOvalElement(int[] shapeOvalElement) {
        for (int ii = 0; ii < count; ii++) {
            Image pointView = new Image(getContext());
            DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(MATCH_CONTENT, MATCH_CONTENT);
            params.width = indicatorWidth;
            params.height = indicatorHeight;
            pointView.setWidth(indicatorWidth);
            pointView.setHeight(indicatorHeight);
            if (ii == 0) {
                pointView.setBackground(new ShapeElement(getContext(), shapeOvalElement[1]));
            } else {
                pointView.setBackground(new ShapeElement(getContext(), shapeOvalElement[0]));
            }
            params.setMargins(ten, twenty, ten, twenty);
            mPointViews.add(pointView);
            circleIndicator.addComponent(pointView, params);
        }
    }

    /**
     * 设置矩形
     */
    private void setShapeRectangleElement() {
        for (int ii = 0; ii < count; ii++) {
            Image pointView = new Image(getContext());
            DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(MATCH_CONTENT, MATCH_CONTENT);
            params.width = indicatorWidth;
            params.height = indicatorHeight;
            pointView.setWidth(indicatorWidth);
            pointView.setHeight(indicatorHeight);
            ShapeElement selectShape;
            if (ii == 0) {
                selectShape = getShapeElement("#ffffff");
            } else {
                selectShape = getShapeElement("#88ffffff");
            }
            pointView.setBackground(selectShape);
            params.setMargins(ten, twenty, ten, twenty);
            mPointViews.add(pointView);
            circleIndicator.addComponent(pointView, params);
        }
    }

    private ShapeElement getShapeElement(String s) {
        ShapeElement selectShape = new ShapeElement();
        RgbColor rgbColor = RgbColor.fromArgbInt(Color.getIntColor(s));
        selectShape.setShape(ShapeElement.RECTANGLE);
        selectShape.setRgbColor(rgbColor);
        selectShape.setCornerRadius(AttrHelper.vp2px(indicatorCornerRadius, getContext()));
        return selectShape;
    }
}
